package com.dd.cloud.user.service.file.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dd.cloud.user.config.HwObsProperties;
import com.dd.cloud.common.constants.FileConstants;
import com.dd.cloud.user.entity.file.AppVersion;
import com.dd.cloud.common.interceptor.UserInterceptor;
import com.dd.cloud.user.mapper.file.AppVersionMapper;
import com.dd.cloud.user.req.file.AppVersionCreateReq;
import com.dd.cloud.user.req.file.AppVersionQueryTermsReq;
import com.dd.cloud.user.req.file.AppVersionUpdateReq;
import com.dd.cloud.user.res.file.HwObsParamRes;
import com.dd.cloud.user.service.file.IAppVersionService;
import com.dd.cloud.common.enums.ZkExceptionEnum;
import com.dd.cloud.common.exception.ZekeException;
import com.dd.cloud.common.utils.ObjectUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;

/**
 * @author Lx
 * @version 1.0
 */
@Slf4j
@Service
public class AppVersionServiceImpl extends ServiceImpl<AppVersionMapper, AppVersion> implements IAppVersionService {
    @Value("${path.imageServer}")
    private String imageServer;
    @Autowired
    private HwObsProperties hwObsProperties;

    /**
     * 最新一次版本key
     */
    public static final String APP_INFO_KEY = "app-info-last";

    @Override
    @Cacheable(value = APP_INFO_KEY, key = "#p1", unless = "#result == null")
    public AppVersion checkAppVersion(String appId, String version, Integer type) {
        log.info("appId:{},version:{},type:{}", appId, version, type);
        QueryWrapper<AppVersion> qw = new QueryWrapper<>();
        qw.lambda().eq(AppVersion::getAppId, appId);
        qw.lambda().eq(AppVersion::getType, type);
        qw.lambda().eq(AppVersion::getStatus, 1);
        qw.lambda().orderByDesc(AppVersion::getCreateDate);
        qw.last("limit 1");
        AppVersion av = getOne(qw);
        log.info("查询最新app版本=====>{}", av);
        if (av == null) {
            return null;
        }
        String[] versions1 = version.split("\\.");
        String[] versions2 = av.getVersion().split("\\.");
        //获取最小长度
        int min = Math.min(versions1.length, versions2.length);
        boolean flag = false;
        for (int i = 0; i < min; ++i) {
            if (versions1[i].compareTo(versions2[i]) < 0) {
                flag = true;
                break;
            }
        }
        if (!flag) {
            if (versions2.length > versions1.length) {
                for (int i = versions1.length; i < versions2.length; i++) {
                    if (!"0".equals(versions2[i])) {
                        flag = true;
                        break;
                    }
                }
            }
        }
        if (flag) {
            log.info("有新版本");
        }
        return av;
    }

    /**
     * @description 分页查询app版本信息
     * @param req:
     * @return IPage<AppVersion>
     * @author czg
     * @date 2023/5/9 17:13
    */
    @Override
    public IPage<AppVersion> queryAppVersionPageTerms(AppVersionQueryTermsReq req) {
        QueryWrapper<AppVersion> qw = new QueryWrapper<>();
        qw.lambda().ne(AppVersion::getStatus, FileConstants.FileStatus.DEL);
        qw.lambda().orderByDesc(AppVersion::getCreateDate);
        IPage<AppVersion> iPage = req.pagePojo();
        iPage = page(iPage, qw);
        return iPage;
    }

    /**
     * @description 添加app版本信息, 需要清除缓存, 方便查出最新数据
     * @CacheEvict 清除缓存注解, value 为缓存的key allEntries是否全部清除, 默认为false
     * @param req:
     * @return AppVersion
     * @author czg
     * @date 2023/5/9 17:05
    */
    @Override
    @CacheEvict(value = APP_INFO_KEY, allEntries=true)
    public AppVersion addAppVersion(AppVersionCreateReq req) {
        QueryWrapper<AppVersion> qw = new QueryWrapper<>();
        qw.lambda().eq(AppVersion::getAppName, req.getAppName());
        qw.lambda().eq(AppVersion::getVersion, req.getVersion())
                .ne(AppVersion::getStatus, FileConstants.FileStatus.DEL);
        int count = count(qw);
        if (count > 0) {
            throw new ZekeException(400, "app版本已存在!");
        }
        AppVersion av = new AppVersion();
        BeanUtils.copyProperties(req, av);

        /**
         * 对象存储小范围使用, 未适配FileSuffix注解,这里用全url, 上传文件全部用对象存储后就要去掉域名
         */
        //av.setAppUrl(req.getAppUrl().replace(hwObsProperties.getDomain(), ""));
        av.setCreateDate(LocalDateTime.now());
        av.setOperId(UserInterceptor.getLoginUserInfo().get().getId());
        av.setStatus(FileConstants.FileStatus.NOMAL);
        boolean flag = save(av);
        if (!flag) {
            throw new ZekeException(ZkExceptionEnum.ADD_ERROR);
        }
        return av;
    }

    /**
     * @description 修改app版本信息
     * @param req:
     * @return AppVersion
     * @author czg
     * @date 2023/5/9 17:07
    */
    @Override
    @CacheEvict(value = APP_INFO_KEY, allEntries=true)
    public AppVersion updateAppVersion(AppVersionUpdateReq req) {
        QueryWrapper<AppVersion> qw = new QueryWrapper<>();
        qw.lambda().eq(AppVersion::getAppName, req.getAppName());
        qw.lambda().eq(AppVersion::getVersion, req.getVersion())
                .ne(AppVersion::getStatus, FileConstants.FileStatus.DEL);
        qw.lambda().ne(AppVersion::getId, req.getId());
        int count = count(qw);
        if (count > 0) {
            throw new ZekeException(400, "app版本已存在!");
        }
        AppVersion av = new AppVersion();
        BeanUtils.copyProperties(req, av);
        /**
         * 对象存储小范围使用, 未适配FileSuffix注解,这里用全url, 上传文件全部用对象存储后就要去掉域名
         */
        //av.setAppUrl(req.getAppUrl().replace(hwObsProperties.getDomain(), ""));
        av.setOperId(UserInterceptor.getLoginUserInfo().get().getId());
        boolean flag = updateById(av);
        if (!flag) {
            throw new ZekeException(ZkExceptionEnum.UPDATE_ERROR);
        }
        return av;
    }

    /**
     * @description 返回华为云obs对象存储参数, 由前端直接调用对象存储上传文件
     * @param :
     * @return HwObsParamRes
     * @author czg
     * @date 2023/5/8 17:45
    */
    @Override
    public HwObsParamRes obsParam() {
        HwObsParamRes res = new HwObsParamRes();
        BeanUtils.copyProperties(hwObsProperties, res);
        return res;
    }

    /**
     * @description 修改app版本状态
     * @param id: 版本id
    	 * @param status: 状态
     * @return void
     * @author czg
     * @date 2023/5/9 17:08
    */
    @Override
    @CacheEvict(value = APP_INFO_KEY, allEntries=true)
    public void updateAppVersionStatus(Integer id, Integer status) {
        AppVersion appVersion = getById(id);
        if (appVersion == null) {
            throw new ZekeException("版本信息不存在");
        }
        if (appVersion.getStatus().equals(status)) {
            return;
        }
        if (!ObjectUtils.refrect(FileConstants.FileStatus.class, status)) {
            throw new ZekeException(ZkExceptionEnum.STATUS_DATA_ERROR);
        }
        appVersion.setStatus(status);
        boolean i = updateById(appVersion);
        if (!i){
            throw new ZekeException(ZkExceptionEnum.UPDATE_ERROR);
        }
    }

    /**
     * @description app下载次数增加
     * @param version: app版本号
    	 * @param type: 下载类型 1链接下载 2自动更新
     * @return void
     * @author czg
     * @date 2024/1/31 9:57
    */
    @Override
    public void updateAppDownloadNum(String version, Integer type) {
        QueryWrapper<AppVersion> qw = new QueryWrapper<>();
        qw.lambda().eq(AppVersion::getVersion, version)
                .eq(AppVersion::getStatus, FileConstants.FileStatus.NOMAL);
        AppVersion one = getOne(qw);
        if (one == null){
            return;
        }
        if (type == 1){
            UpdateWrapper<AppVersion> uw = new UpdateWrapper<>();
            uw.lambda().eq(AppVersion::getVersion, version)
                    .eq(AppVersion::getStatus, FileConstants.FileStatus.NOMAL)
                    .setSql("`download_num` = `download_num` + 1");
            update(uw);
        }
        if (type == 2){
            UpdateWrapper<AppVersion> uw = new UpdateWrapper<>();
            uw.lambda().eq(AppVersion::getVersion, version)
                    .eq(AppVersion::getStatus, FileConstants.FileStatus.NOMAL)
                    .setSql("`auto_update_num` = `auto_update_num` + 1");
            update(uw);
        }
    }
}
